package com.cheche.dn.domain.admin;

import com.cheche.dn.Result;
import com.cheche.dn.common.Pageable;
import com.cheche.dn.common.base.BaseController;
import com.cheche.dn.error.ErrorCode;
import com.google.common.base.Strings;
import com.google.common.collect.Lists;
import com.google.common.collect.Sets;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.security.crypto.password.PasswordEncoder;
import org.springframework.web.bind.annotation.*;
import org.springframework.web.multipart.MultipartFile;

import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Set;

/**
 * Controller - 管理员操作
 * Created by cheshun on 15/8/23.
 */
@RestController
public class AdminController extends BaseController {

    @Autowired
    private PasswordEncoder passwordEncoder;
    @Autowired
    private RoleService roleService;
    @Autowired
    private AdminService adminService;

    /**
     * 创建管理员
     * 已加入权限列表
     * @see Authority Authority.ADMINS_POST
     * @param admin 管理员属性
     * @param roleIds 权限ID
     * @return 管理员实体
     */
    @RequestMapping(value = ADMINS_URL, method = RequestMethod.POST)
    public Object admins(Admin admin, @RequestParam(value = "roleId", required = false) Long[] roleIds) {
        if (!isValid(admin)) {
            return currentValidError();
        }

        if (roleIds != null) {
            List<Role> roleList = service.findList(Role.class, roleIds);
            admin.setRoles(Sets.newHashSet(roleList));
        }
        service.save(admin);
        return Result.success("admin", admin);
    }

    /**
     * 获取当前管理员信息
     * @see Authority Authority.ADMINS_SELF_GET
     * @return 当前管理员
     */
    @RequestMapping(value = ADMINS_SELF_URL, method = RequestMethod.GET)
    public Object admins() {
        Admin admin = currentAdmin();
        return Result.success("admin", admin).append("roles", admin.getRoles());
    }

    /**
     * 获取管理员详情
     * @see Authority Authority.ADMINS_ID_GET
     * @param id ID
     * @return 管理员详情
     */
    @RequestMapping(value = ADMINS_ID_URL, method = RequestMethod.GET)
    public Object admins(@PathVariable Long id) {
        Admin admin = service.find(Admin.class, id);
        return Result.success("admin", admin).append("roles", admin.getRoles());
    }

    /**
     * 获取多个管理员详情
     * @see Authority Authority.ADMINS_GET
     * @param ids IDS
     * @return 管理员详情
     */
    @RequestMapping(value = ADMINS_URL, method = RequestMethod.GET, params = {"id"})
    public Object admins(@RequestParam("id") Long[] ids) {
        List<Map<String, Object>> result = Lists.newArrayList();
        List<Admin> admins = service.findList(Admin.class, ids);
        for (Admin admin : admins) {
            Map<String, Object> map = new HashMap<>(2);
            map.put("admin", admin);
            map.put("roles", admin.getRoles());
            result.add(map);
        }
        return Result.success("admins", result);
    }

    /**
     * 获取管理员列表
     * @see Authority Authority.ADMINS_GET
     * @param pn 页码
     * @param limit 每页数量
     * @return 管理员列表
     */
    @RequestMapping(value = ADMINS_URL, method = RequestMethod.GET)
    public Object admins(@RequestParam(defaultValue = "1") int pn,
                         @RequestParam(defaultValue = "10") int limit,
                         @RequestParam(defaultValue = Dt.PAGE) String dt) {
        Pageable pageable = new Pageable.Builder(pn, limit).build();
        if (dt.equals(Dt.LIST)) {
            return Result.success("admins", service.findList(Admin.class, pageable));
        }
        return Result.success("page", service.findPage(Admin.class, pageable));
    }

    @RequestMapping(value = ADMINS_URL, method = RequestMethod.GET, headers = {"version=v2"})
    public Object admins2(@RequestParam(defaultValue = "1") int pn,
                          @RequestParam(defaultValue = "10") int limit,
                          @RequestParam(defaultValue = Dt.PAGE) String dt) {
        Pageable pageable = new Pageable.Builder(pn, limit).build();
        if (dt.equals(Dt.LIST)) {
            return Result.success("admins", service.findList(Admin.class, pageable));
        }
        return Result.success("page", service.findPage(Admin.class, pageable));
    }

    /**
     * 修改当前管理员密码
     * @see Authority Authority.ADMINS_PASSWORD_PATCH
     * @param newPassword 新密码
     * @param oldPassword 旧密码
     * @return success/error
     */
    @RequestMapping(value = ADMINS_PASSWORD_URL, method = RequestMethod.PATCH)
    public Object adminsPassword(@RequestParam String newPassword,
                                 @RequestParam String oldPassword) {
        Admin admin = currentAdmin();
        if (passwordEncoder.matches(oldPassword, admin.getPassword())) {
            return adminService.resetPassword(admin, newPassword);
        }
        return Result.error(ErrorCode.PASSWORD_ERROR);
    }

    /**
     * 重置指定管理员密码
     * @see Authority Authority.ADMINS_ID_PASSWORD_PATCH
     * @param password 密码
     * @param id ID
     * @return success/error
     */
    @RequestMapping(value = ADMINS_ID_PASSWORD_URL, method = RequestMethod.PATCH)
    public Object adminsPassword(@RequestParam String password, @PathVariable Long id) {
        Admin admin = service.find(Admin.class, id);
        return adminService.resetPassword(admin, password);
    }

    /**
     * 添加用户角色
     * @see Authority Authority.ADMINS_ID_ROLES_POST
     * @param id 管理员ID
     * @param roleIds 角色ID
     * @return 管理员
     */
    @RequestMapping(value = ADMINS_ID_ROLES_URL, method = RequestMethod.POST)
    public Object adminsRoles(@PathVariable Long id, @RequestParam("roleId") Long[] roleIds) {
        Admin admin = service.find(Admin.class, id);
        Set<Role> roles = admin.getRoles();
        roles.addAll(service.findList(Role.class, roleIds));
        admin = service.update(admin);
        return Result.success("admin", admin).append("roles", admin.getRoles());
    }

    /**
     * 删除用户角色
     * @see Authority Authority.ADMINS_ID_ROLES_DELETE
     * @param id 管理员ID
     * @param roleIds 角色ID
     * @return 管理员
     */
    @RequestMapping(value = ADMINS_ID_ROLES_URL, method = RequestMethod.DELETE)
    public Object adminsRolesDelete(@PathVariable Long id, @RequestParam("roleId") Long[] roleIds) {
        Admin admin = service.find(Admin.class, id);
        Set<Role> roles = admin.getRoles();
        for (Long roleId : roleIds) {
            for (Role role : roles) {
                if (role.getId().equals(roleId)) {
                    roles.remove(role);
                    break;
                }
            }
        }
        admin = service.update(admin);
        return Result.success("admin", admin).append("roles", admin.getRoles());
    }

    /**
     * 获取权限列表
     * @see Authority Authority.AUTHORITIES_GET
     * @return 权限列表
     */
    @RequestMapping(value = AUTHORITIES_URL, method = RequestMethod.GET)
    public Object authorities() {
        return Result.success("authorities", service.findAll(Authority.class));
    }

    /**
     * 创建角色
     * @see Authority Authority.ROLES_POST
     * @param role 角色属性
     * @param authorityIds 权限ID
     * @return 新角色
     */
    @RequestMapping(value = ROLES_URL, method = RequestMethod.POST)
    public Object roles(Role role, @RequestParam(value = "authorityId", required = false) Long[] authorityIds) {
        if (!isValid(role)) {
            return currentValidError();
        }
        if (authorityIds != null) {
            Set<Authority> authorities = roleService.findAuthoritySet(authorityIds);
            role.setAuthorities(authorities);
        }
        role.setIsSystem(false);
        service.save(role);
        return Result.success("role", role);
    }

    /**
     * 获取角色列表
     * @see Authority Authority.ROLES_GET
     * @return 角色列表
     */
    @RequestMapping(value = ROLES_URL, method = RequestMethod.GET)
    public Object roles() {
        return Result.success("roles", service.findAll(Role.class));
    }

    /**
     * 修改角色信息
     * @see Authority Authority.ROLES_PUT
     * @param role 角色属性
     * @param authorityIds 权限ID
     * @return 修改后角色
     */
    @RequestMapping(value = ROLES_URL, method = RequestMethod.PUT)
    public Object rolesUpdate(Role role, @RequestParam(value = "authorityId", required = false) Long[] authorityIds) {
        Role currentRole = service.find(Role.class, role.getId());
        if (currentRole != null) {
            if (currentRole.getIsSystem()) {
                return Result.error("Built-in permission system can not be deleted");
            }
            if (!Strings.isNullOrEmpty(role.getName())) {
                currentRole.setName(role.getName());
            }
            if (!Strings.isNullOrEmpty(role.getDescription())) {
                currentRole.setDescription(role.getDescription());
            }
            if (authorityIds != null) {
                Set<Authority> authorities = roleService.findAuthoritySet(authorityIds);
                currentRole.setAuthorities(authorities);
            }
            currentRole = service.update(currentRole);
            return Result.success("role", currentRole);
        }
        return Result.error("role is not exist");
    }

    /**
     * 给角色添加权限
     * @see Authority Authority.ROLES_ID_AUTHORITIES_POST
     * @param id 角色ID
     * @param authorityIds 权限ID
     * @return 角色
     */
    @RequestMapping(value = ROLES_ID_AUTHORITIES_URL, method = RequestMethod.POST)
    public Object rolesAuthority(@PathVariable Long id, @RequestParam("authorityId") Long[] authorityIds) {
        Role role = service.find(Role.class, id);
        Set<Authority> authorities = role.getAuthorities();
        authorities.addAll(service.findList(Authority.class, authorityIds));
        role.setAuthorities(authorities);
        role = service.update(role);
        return Result.success("role", role);
    }

    /**
     * 删除角色权限
     * @see Authority Authority.ROLES_ID_AUTHORITIES_DELETE
     * @param id 角色ID
     * @param authorityIds 权限ID
     * @return 角色
     */
    @RequestMapping(value = ROLES_ID_AUTHORITIES_URL, method = RequestMethod.DELETE)
    public Object rolesAuthorityDelete(@PathVariable Long id, @RequestParam("authorityId") Long[] authorityIds) {
        Role role = service.find(Role.class, id);
        if (role != null) {
            Set<Authority> authorities = role.getAuthorities();
            for (Long authId : authorityIds) {
                for (Authority authority : authorities) {
                    if (authority.getId().equals(authId)) {
                        authorities.remove(authority);
                        break;
                    }
                }
            }
            role = service.update(role);
            return Result.success("role", role);
        }
        return Result.error("role is not exist");
    }

    /**
     * 删除角色
     * @see Authority Authority.ROLES_DELETE
     * @param ids IDS
     * @return success
     */
    @RequestMapping(value = ROLES_URL, method = RequestMethod.DELETE)
    public Object rolesDelete(@RequestParam("id") Long[] ids) {
        return roleService.delete(ids);
    }

    /**
     * 删除角色
     * @see Authority Authority.ROLES_ID_DELETE
     * @param id ID
     * @return success
     */
    @RequestMapping(value = ROLES_ID_URL, method = RequestMethod.DELETE)
    public Object rolesDelete(@PathVariable Long id) {
        return roleService.delete(id);
    }

    /**
     * 获取角色详情
     * @see Authority Authority.ROLES_ID_GET
     * @param id ID
     * @return 角色详情
     */
    @RequestMapping(value = ROLES_ID_URL, method = RequestMethod.GET)
    public Object roles(@PathVariable Long id) {
        Role role = service.find(Role.class, id);
        return Result.success("role", role).append("admins", role.getAdmins());
    }

}
